<template>
	<view class="container">
		<view class="level">
			当前关：{{levelConfigure.gameLevels}}
		</view>
		<canvas canvas-id="gameCanvas" @touchstart="handleTouchStart" @touchmove="handleTouchMove"
			@touchend="handleTouchEnd" @tap="handleCanvasTap" class="canvas"></canvas>
		<view class="progress-box">
			<progress :percent="process" activeColor="#10AEFF" stroke-width="3" />
		</view>
		<!-- 状态提示 -->
		<view class="status-overlay" v-if="isPaused || isGameOver">
			<text v-if="isPaused" class="status-text">{{ tip }}</text>
			<text v-if="isGameOver" class="status-text">
				游戏结束！\n得分：{{ score }}\n点击重试
			</text>
		</view>
		<view class="btn">
			<button @click="togglePause()"> {{ gameStatus }} </button>
			<button @click="backHome()">返回主菜单</button>
		</view>
	</view>
</template>

<script>
	import gameLevel from '@/pages/level/levels.js'
	export default {
		data() {
			return {
				ctx: null, // canvas画布
				canvasWidth: 750,
				canvasHeight: 750,
				dpr: 1,
				snake: {
					x: 375, // 蛇坐标
					y: 375,
					body: [], // 蛇身
					length: 1, // 长度
					speed: 5, // 速度
					currentAngle: Math.PI / 2, // 当前角度
					targetAngle: Math.PI / 2 // 目标角度
				},
				touchStart: { // 触屏坐标
					x: 0,
					y: 0
				},
				isTouching: false, // 触屏
				animationFrameId: null, // 动画定时器
				food: { // 食物坐标
					x: 305,
					y: 600
				},
				score: 0, // 分数
				// isPaused: false,
				// isGameOver: false,
				initialLength: 1, // 初始长度
				growthPerFood: 1, // 生长长度
				gameState: 'playing', // 游戏状态：playing/paused/gameover 
				lastFrameTime: 0, // 最后一帧时间
				levelConfigure: { // 关卡配置
					gameLevels: 1,
					initialSpeed: 3,
					foodNumber: 10
				},
				tip: '已暂停\n点击继续', // 提示文案
				passed: false, // 过关状态
				process: 0 // 进度条
			}
		},
		computed: {
			// 暂停
			isPaused() {
				return this.gameState === 'paused'
			},
			// 游戏结束
			isGameOver() {
				return this.gameState === 'gameover'
			},
			// 按钮文案
			gameStatus() {
				if (this.gameState == 'paused') {
					return '继续'
				} else if (this.gameState == 'playing') {
					return '暂停'
				}
			},
		},
		watch: {
			// 监听蛇长度改变进度条
			'snake.length': function(val,oldVal) {
				this.process = (this.snake.length - 1) / this.levelConfigure.foodNumber * 100
			}
		},
		mounted() {
			// 取关卡记录
			if (uni.getStorageSync('level')) {
				let nowLevel = uni.getStorageSync('level') - 1;
				this.levelConfigure = gameLevel[nowLevel]
			} else {
				this.levelConfigure = gameLevel[0]
			}
			// 初始化画布
			this.initCanvas()
			// 初始化蛇
			this.initSnake()
			// 开启动画
			this.gameLoop()
		},
		beforeDestroy() {
			// 清除动画循环
			if (this.animationFrameId) {
				cancelAnimationFrame(this.animationFrameId)
			}
		},
		methods: {
			// 初始化画布
			initCanvas() {
				// 获取设备dpr 创建画布
				const systemInfo = uni.getSystemInfoSync()
				this.dpr = systemInfo.pixelRatio
				this.canvasWidth = systemInfo.windowWidth * this.dpr
				this.canvasHeight = 375 * this.dpr
				this.ctx = uni.createCanvasContext('gameCanvas', this)
				this.ctx.scale(this.dpr, this.dpr)
			},

			initSnake() {
				// 初始化蛇身
				this.snake.body = Array.from({
					length: this.snake.length
				}, () => ({
					x: this.snake.x,
					y: this.snake.y
				}))
			},
			// 触屏
			async handleTouchStart(e) {
				if (this.isPaused) !this.isPaused
				const touch = e.touches[0]
				this.touchStart = this.convertTouchPos(touch)
				this.isTouching = true

				const pos = await this.convertTouchPos(touch)
				this.calculateAngle(pos.x, pos.y)
			},
			// 触屏移动
			async handleTouchMove(e) {
				console.log('移动');
				if (!this.isTouching) return
				const touch = e.touches[0]
				const pos = await this.convertTouchPos(touch)
				this.calculateAngle(pos.x, pos.y)
			},
			// 触屏结束
			handleTouchEnd() {
				console.log('结束');
				this.isTouching = false
			},

			convertTouchPos(touch) {
				// 将触摸点转换为Canvas坐标
				const query = uni.createSelectorQuery().in(this)
				return new Promise(resolve => {
					query.select('.canvas').boundingClientRect(rect => {
						console.log(touch.pageX, rect.left, rect.top,this.canvasWidth, rect.width,'将触摸点转换为Canvas坐标');
						resolve({
							x: (touch.pageX - rect.left) * (this.canvasWidth / rect.width),
							y: (touch.pageY - rect.top) * (this.canvasHeight / rect.height)
						})
					}).exec()
				})
			},
			// 计算角度
			calculateAngle(touchX, touchY) {
				const deltaX = touchX - this.snake.x
				const deltaY = touchY - this.snake.y
				// 使用反正切函数求得角度
				this.snake.targetAngle = Math.atan2(deltaY, deltaX)
			},

			// 更新蛇
			updateSnake() {
				if (this.isPaused || this.isGameOver) return
				// 角度平滑过渡
				let angleDiff = this.snake.targetAngle - this.snake.currentAngle
				// 如果相差角度大于180度，应反方向旋转; 控制角度差在(-PI,PI)
				angleDiff = ((angleDiff + Math.PI) % (2 * Math.PI)) - Math.PI
				this.snake.currentAngle += Math.sign(angleDiff) * Math.min(
					Math.abs(angleDiff),
					15 * Math.PI / 180 // 最大转向速度15度/帧
				)

				// 计算移动矢量
				const moveX = Math.cos(this.snake.currentAngle) * this.snake.speed
				const moveY = Math.sin(this.snake.currentAngle) * this.snake.speed
				console.log(moveX,moveY);
				// 更新位置
				this.snake.x += moveX
				this.snake.y += moveY
				console.log(this.snake.x,this.snake.y,'xy');
				// 边界检测
				if (this.snake.x < 0 || this.snake.y < 0 || this.snake.y > this.canvasHeight - 90  || this.snake.x > this
					.canvasWidth - 40) {
						console.log('边界',this.snake.x,this.snake.y,this.canvasHeight,this
					.canvasWidth);
					this.gameOver()
				}

				// 更新身体
				this.snake.body.unshift({
					x: this.snake.x,
					y: this.snake.y
				})
				if (this.snake.body.length > this.snake.length) {
					this.snake.body.pop()
				}

				// 检测食物碰撞
				this.checkCollisions()
				
				// 蛇自身碰撞检测
				if (this.checkSelfCollision()) {
					this.gameOver()
				}
			},
			// 绘制
			draw() {
				this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
				
				// 绘制蛇身
				this.snake.body.forEach((pos, index) => {
					this.ctx.beginPath()
					this.ctx.arc(
						pos.x / this.dpr,
						pos.y / this.dpr,
						10,
						0,
						Math.PI * 2
					)
					this.ctx.fillStyle = `rgba(0, 200, 0, ${Math.max(0.3, 1 - index * 0.05)})`
					this.ctx.fill()
				})

				// 绘制方向指示器
				// if (this.isTouching) {
				// 	this.ctx.beginPath()
				// 	this.ctx.moveTo(this.snake.x / this.dpr, this.snake.y / this.dpr)
				// 	this.ctx.lineTo(
				// 		(this.snake.x + Math.cos(this.snake.currentAngle) * 30) / this.dpr,
				// 		(this.snake.y + Math.sin(this.snake.currentAngle) * 30) / this.dpr
				// 	)
				// 	this.ctx.strokeStyle = 'red'
				// 	this.ctx.lineWidth = 3
				// 	this.ctx.stroke()
				// }

				// 绘制食物
				this.ctx.beginPath()
				this.ctx.arc(
					this.food.x / this.dpr,
					this.food.y / this.dpr,
					10, 0, Math.PI * 2
				)
				this.ctx.fillStyle = '#6ac4ff'
				this.ctx.fill()

				// 在控制台输出物理尺寸
				  console.log('Canvas物理尺寸:', this.canvasWidth, this.canvasHeight)
				  console.log('当前蛇头位置:', this.snake.x, this.snake.y)
				this.ctx.draw()
			},

			// 生成不重叠的食物
			generateFood() {
				const maxAttempts = 100
				for (let i = 0; i < maxAttempts; i++) {
					this.food = {
						x: Math.random() * (this.canvasWidth - 120) + 10,
						y: Math.random() * (this.canvasHeight - 120) + 10
					}
					// 检查是否与蛇身重叠
					let isValid = true
					for (const segment of this.snake.body) {
						const dx = this.food.x - segment.x
						const dy = this.food.y - segment.y
						if (Math.sqrt(dx * dx + dy * dy) < 30) {
							isValid = false
							break
						}
					}
					if (isValid) break
				}
			},

			// 食物碰撞检测
			checkCollisions() {
				const dx = this.snake.x - this.food.x
				const dy = this.snake.y - this.food.y
				if (Math.sqrt(dx * dx + dy * dy) < 50) {
					this.snake.length += this.growthPerFood
					this.score += 100
					// 过关，记录关卡
					if (this.snake.length == this.levelConfigure.foodNumber + 1) {
						uni.setStorageSync('level', this.levelConfigure.gameLevels + 1)
						this.tip = `当前关卡:${this.levelConfigure.gameLevels + 1}\n点击开始`
						this.passed = true
						this.togglePause()
						return
					}

					this.generateFood()
					// 增加难度
					if (this.snake.length % 3 == 0) {
						this.increaseSpeed()
					}
				}
			},
			// 蛇自身碰撞检测
			checkSelfCollision() {
				// 从第20节身体开始检测
				for (let i = 15; i < this.snake.body.length; i++) {
					const dx = this.snake.x - this.snake.body[i].x
					const dy = this.snake.y - this.snake.body[i].y
					if (dx * dx + dy * dy < 225) { // 15^2=225
						return true
					}
				}
				return false
			},

			handleCanvasTap() {
				if (this.passed) {
					this.passed = !this.passed
					this.restartGame()
				} else if (this.isGameOver) {
					this.restartGame()
				} else if (this.gameState === 'playing') {
					// this.togglePause()
				} else if (this.isPaused) {
					this.resumeGame()
				}
			},
			// 游戏暂停
			togglePause() {
				if (this.passed) {
					this.gameState = 'paused'
					clearTimeout(this.animationFrameId)
					return
				}
				if (this.gameState == 'playing') {
					this.gameState = 'paused'
					this.tip = '已暂停\n点击继续'
					clearTimeout(this.animationFrameId)
				} else if (this.isPaused) {
					this.resumeGame()
				}
			},
			// 恢复游戏
			resumeGame() {
				if (this.isGameOver) return
				this.gameState = 'playing'
				this.lastFrameTime = Date.now()
				this.gameLoop()
			},

			// 游戏结束
			gameOver() {
				this.gameState = 'gameover'
				clearTimeout(this.animationFrameId)
			},

			// 重新开始
			restartGame() {
				// 重置游戏数据
				let nowLevel = 0
				if (uni.getStorageSync('level')) {
					nowLevel = uni.getStorageSync('level') - 1;
				}
				console.log(gameLevel[nowLevel], this.levelConfigure);
				Object.assign(this.levelConfigure, gameLevel[nowLevel])

				this.snake = {
					x: this.canvasWidth / 2,
					y: this.canvasHeight / 2,
					body: [],
					length: this.initialLength,
					speed: this.levelConfigure.initialSpeed,
					currentAngle: Math.PI / 2,
					targetAngle: Math.PI / 2
				}
				this.score = 0
				this.initSnake()
				this.generateFood()

				// 重置游戏状态
				this.gameState = 'playing'
				this.lastFrameTime = Date.now()

				// 重启游戏循环
				this.gameLoop()
			},
			// 循环动画
			gameLoop() {
				if (this.gameState !== 'playing') return

				const now = Date.now()
				const deltaTime = now - this.lastFrameTime

				// 基于时间的更新（保持60FPS速度）
				if (deltaTime >= 16) {
					this.updateSnake()
					this.draw()
					this.lastFrameTime = now - (deltaTime % 16)
				}

				// 保持循环
				this.animationFrameId = setTimeout(() => {
					this.gameLoop()
				}, 0)
			},
			// 返回主页
			backHome() {
				this.togglePause()
				uni.navigateBack()
			},
			// 加强速度
			increaseSpeed() {
				this.snake.speed += 1
			},
			onpagehide() {
				clearTimeout(this.animationFrameId)
			}
		}
	}
</script>

<style>
	.container {
		width: 100vw;
		height: 100vh;
		/* display: flex; */
		/* justify-content: center; */
		/* align-items: center; */
	}

	.canvas {
		width: 750rpx;
		height: 750rpx;
		border: 2px solid;
		box-sizing: border-box;
		background-color: #ffffff;
		touch-action: none;
	}

	.score-board {
		position: fixed;
		top: 20rpx;
		left: 20rpx;
		font-size: 36rpx;
		color: #333;
		z-index: 2;
	}

	.game-over {
		position: fixed;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		background: rgba(0, 0, 0, 0.8);
		color: white;
		padding: 30rpx 60rpx;
		border-radius: 16rpx;
		font-size: 40rpx;
	}

	.status-overlay {
		position: absolute;
		top: 35%;
		left: 50%;
		transform: translate(-50%, -50%);
		background: rgba(0, 0, 0, 0.8);
		padding: 40rpx 80rpx;
		border-radius: 20rpx;
		text-align: center;
	}

	.status-text {
		color: white;
		font-size: 36rpx;
		line-height: 1.5em;
	}

	.btn button {
		width: 80%;
		font-size: 14px;
		background-color: #91c61d;
		color: #7373ad;
		margin: 10px auto;
	}
	.progress-box {
		margin-top: 10px;
		padding: 0 5px;
	}
</style>